package controller;

import java.util.HashMap;
import java.util.List;

import model.Dictionary;
import model.Rack;
import model.ScrabbleGame;
import model.Tile;
import model.listeners.PlayerListener;
import model.listeners.TurnListener;
import util.Coordinate;
import view.IBoardView;
import view.ILogView;
import view.IPlayersView;
import view.IRackView;
import view.swing.popup.EndGameWindow;

/**
 * 
 * @author Lucile Gramusset et Guillaume Poussel
 * 
 */
public class GameController extends AbstractController {

    private ScrabbleGame scrabbleGame;

    private BoardController boardController;
    private PlayerController playerController;
    private RackController rackController;
    private ActionController actionController;
    private LogController logController;

    /**
     * Crée un contrôleur de jeu
     * 
     * @param sg
     *            Modèle du jeu de scrabble
     */
    public GameController(ScrabbleGame sg) {
        super(null);
        scrabbleGame = sg;
        sg.start();
    }

    /**
     * Crée tous les contrôleurs nécessaires à l'application
     */
    public void init(IBoardView boardView, ILogView logView,
            IPlayersView playersView, IRackView rackView) {

        boardController = new BoardController(this, boardView);

        logController = new LogController(this, logView);

        playerController = new PlayerController(this, playersView);

        rackController = new RackController(this, rackView);

        actionController = new ActionController(this);

    }

    /**
     * @return Contrôleur du plateau
     */
    public BoardController getBoardController() {
        return boardController;
    }

    /**
     * @return Contrôleur des joueurs
     */
    public PlayerController getPlayerController() {
        return playerController;
    }

    /**
     * @return Contrôleur du rack
     */
    public RackController getRackController() {
        return rackController;
    }

    /**
     * @return Contrôleur des actions (jouer, passer...)
     */
    public ActionController getActionController() {
        return actionController;
    }

    /**
     * @return Contrôleur des logs
     */
    public LogController getLogController() {
        return logController;
    }

    /**
     * Joue un coup
     * 
     * @param tiles
     *            Les tuiles posées par l'utilisateur
     */
    public void playTurn(HashMap<Coordinate, Tile> tiles) {
        if (scrabbleGame.play(tiles)) {
            getBoardController().fixAllTiles();
            scrabbleGame.nextPlayer();
        }
    }

    /**
     * Ajoute un "listener" sur le joueur en cours
     * 
     * @param pl
     *            Le "listener" à ajouter
     */
    public void addPlayerListener(PlayerListener pl) {
        this.scrabbleGame.addPlayerListener(pl);
    }

    /**
     * Passe son tour en comptant le changement comme un "passe"
     */
    public void skipTurn() {
        skipTurn(true);
    }

    /**
     * Passe son tour
     * 
     * @param reallySkip
     *            Compter ou non le changement comme un "passe"
     */
    public void skipTurn(boolean reallySkip) {
            scrabbleGame.skipTurn(reallySkip);
    }

    /**
     * Echange des tuiles
     * 
     * @param choice
     *            Tuiles à échanger
     */
    public void swap(List<Tile> choice) {
        scrabbleGame.swapTiles(choice);
    }

    /**
     * Ajouter un "listener" sur les tours joués
     * 
     * @param tl
     *            Le "listener" à ajouter
     */
    public void addTurnListener(TurnListener tl) {
        this.scrabbleGame.addTurnListener(tl);
    }

    /**
     * Vérifie un mot dans le dictionnaire
     * 
     * @param word
     *            Le mot à vérifier
     * @return <code>true</code> si le mot est dans le dictionnaire,
     *         <code>false</code> sinon.
     */
    public boolean checkWord(String word) {
        return Dictionary.getInstance().contains(word);
    }

    /**
     * Termine le jeu, et affiche la fenêtre de fin
     */
    public void endGame() {
        scrabbleGame.endGame();
        EndGameWindow egw = new EndGameWindow(scrabbleGame.getIPlayers());
        egw.showWindow();
        System.exit(0);
    }

    /**
     * Récupère le rack en cours
     * 
     * @return Le rack du joueur en cours
     */
    public Rack getCurrentRack() {
        return this.scrabbleGame.getCurrentPlayer().getRack();
    }

}
